﻿//===============================================================================
// Microsoft Innovation Centre - Western Europe
// Copyright (c) 2008 Microsoft Corporation. All rights reserved.
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE.
//===============================================================================
// The example companies, organizations, products, domain names,
// e-mail addresses, logos, people, places, and events depicted
// herein are fictitious.  No association with any real company,
// organization, product, domain name, email address, logo, person,
// places, or events is intended or should be inferred.
//===============================================================================

using System;
using System.Collections.Generic;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Markup;

namespace Microsoft.WVB.Framework.AdControls
{
    /// <summary>
    /// Provides the base class for different Ad format (Image, Video, Xap and so on).
    /// </summary>
    public abstract class AdBase : Control
    {
        protected const string AdMarkerText = "MiddleTimecode";
        protected const string AdMarkerType = "AdCallback";

        protected int BeginReachCount = 0;
        protected int MidReachCount = 0;
        protected int EndReachCount = 0;

        protected AdContext AdContext { get; set; }
        //protected abstract string StylePath { get; }

        /// <summary>
        /// A <see cref="Boolean"/> indicating whether of not the Ad is Muted/unmuted.
        /// </summary>
        /// <remarks>This applies essentially to derived Ads format that includes Video or Audio.
        /// </remarks>
        public Boolean IsMuted
        {
            get { return (Boolean)GetValue(IsMutedProperty); }
            set { SetValue(IsMutedProperty, value); }
        }
        public static readonly DependencyProperty IsMutedProperty = null;

        /// <summary>
        /// A <see cref="Boolean"/> indicating if the Ad is ready for being displayed.
        /// i.e. the image has been downloaded, the video has been buffered, there is not 404 execeptions
        /// when trying to get access to the resource and so on.
        /// </summary>
        public Boolean IsReady
        {
            get { return (Boolean)GetValue(IsReadyProperty); }
            set { SetValue(IsReadyProperty, value); }
        }
        public static readonly DependencyProperty IsReadyProperty = null;

        /// <summary>
        /// Due to asynchronous delays when buffering or downloading medias, we need to queue all the actions
        /// against the MediaElement or any other controls that will be manipulating the Media.
        /// </summary>
        protected Queue<System.Action> QueuedActions = new Queue<System.Action>();

        /// <summary>
        /// The static constructor
        /// </summary>
        static AdBase()
        {
            IsMutedProperty = DependencyProperty.Register("IsMuted", typeof(Boolean), typeof(AdBase), new PropertyMetadata(new PropertyChangedCallback(OnIsMutedChanged)));
            IsReadyProperty = DependencyProperty.Register("IsReady", typeof(Boolean), typeof(AdBase), new PropertyMetadata(new PropertyChangedCallback(OnIsReadyChanged)));
        }

        public AdBase()
        {
            //this.SetStyle();
        }

        static void OnIsMutedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((AdBase)d).OnIsMutedChanged((bool)e.OldValue, (bool)e.NewValue);
        }

        protected virtual void OnIsMutedChanged(bool oldValue, bool newValue) { }

        static void OnIsReadyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((AdBase)d).OnIsReadyChanged((bool)e.OldValue, (bool)e.NewValue);
        }

        protected virtual void OnIsReadyChanged(bool oldValue, bool newValue) { }

        /// <summary>
        /// When implemented, this method provides the placeholder where developer buffers the Ad based upon
        /// the provided <see cref="AdContext"/>.
        /// </summary>
        /// <param name="adContext">A <see cref="AdContext"/> object containing all information with regards
        /// to the Ad, its location, its format and other parameter needed to track an Ad impression.
        /// </param>
        public abstract void Buffer(AdContext adContext);

        /// <summary>
        /// When implemented, this method provides the placeholder where developer starts the Ad.
        /// I.e. it could do a MediaElement.Start() or an Animation.Begin()
        /// This does not really apply to static Images or Content.
        /// </summary>
        public abstract void Start();

        /// <summary>
        /// Event fires when the Ad stops. This event should be fired when an interactive user stops 
        /// the Ad display. user can close the Ad or stop an animation, then this event needs to be fired.
        /// </summary>
        public event EventHandler AdStopped;

        /// <summary>
        /// Throws the <see cref="AdStopped"/> event.
        /// </summary>
        /// <param name="sender">An <see cref="Object"/> which is the originator object</param>
        /// <param name="e">An <see cref="EventArgs"/> object</param>
        protected virtual void OnAdStopped(object sender, EventArgs e)
        {
            if (AdStopped != null)
            {
                AdStopped(this, e);
            }
        }

        /// <summary>
        /// Event fires when the Ads ends. This event should only be fired when the Ad media stops 
        /// without human interactivity. I.e when the Video stops or when an animation stops.
        /// </summary>
        public event EventHandler AdEnded;

        /// <summary>
        /// Throws the <see cref="AdEnded"/> event.
        /// </summary>
        /// <param name="sender">An <see cref="Object"/> which is the originator object</param>
        /// <param name="e">An <see cref="EventArgs"/> object</param>
        protected virtual void OnAdEnded(object sender, EventArgs e)
        {
            if (AdEnded != null)
            {
                AdEnded(this, e);
            }
        }

        /// <summary>
        /// Notifies when an Ad need to report its Impression.
        /// </summary>
        public event EventHandler<AdTrackedEventArgs> AdImpressionTracked;

        /// <summary>
        /// Throws <see cref="AdImpressionTracked"/> events.
        /// </summary>
        /// <param name="sender">An <see cref="Object"/> which is the originator object</param>
        /// <param name="e">An <see cref="EventArgs"/> object</param>
        protected virtual void OnAdImpressionTracked(object sender, AdTrackedEventArgs e)
        {
            EventHandler<AdTrackedEventArgs> handler = AdImpressionTracked;

            if (handler != null)
            {
                AdImpressionTracked(this, e);
            }
        }
    }
}
